package br.uff.mic1.model;

public class Mic1 {

	public static final int BARRAMENTO_A = 0;
	public static final int BARRAMENTO_B = 1;
	public static final int BARRAMENTO_C = 2;
 	
	private String mpc;
	private String latchA;
	private String latchB;
	private String mar;
	private String mbr;
	
	//Auxiliares
	private String barramentoA;
	private String barramentoB;
	private String barramentoC;
	private String saidaAMUX;
	private String saidaALU;
	private String saidaDeslocador;
	private String saidaMMUX;
	
	private ALU alu;
	private AMUX amux;
	private BancoRegistradores bancoDeRegistradores;
	private Decodificador decodificadorA;
	private Decodificador decodificadorB;
	private Decodificador decodificadorC;
	private Deslocador deslocador;
	private INCR incr;
	private MemoriaDeControle memoriaDeControle;
	private MIR mir;
	private MMUX mmux;
	
	public Mic1()
	{
	}
	
	public Mic1(String microprograma)
	{
		this.mpc = "00000000";
		this.latchA = "";
		this.latchB = "";
		this.mar = "";
		this.mbr = "";
		this.alu = new ALU();
		this.amux = new AMUX();
		this.bancoDeRegistradores = new BancoRegistradores();
		this.decodificadorA = new Decodificador();
		this.decodificadorB = new Decodificador();
		this.decodificadorC = new Decodificador();
		this.deslocador = new Deslocador();
		this.incr = new INCR();
		this.memoriaDeControle = new MemoriaDeControle(microprograma);
		this.mir = new MIR();
		this.mmux = new MMUX();
	}
	
	
	public void atualizaMPC()
	{
		this.mpc = this.saidaMMUX;
	}
	
	public String getMPC()
	{
		return this.mpc;
	}

	public String getLatchA() {
		return latchA;
	}

	public void populaLatchA() {
		this.latchA = this.barramentoA;
	}

	public String getLatchB() {
		return latchB;
	}

	public void populaLatchB() {
		this.latchB = this.barramentoB;
	}
	
	public String getMAR() {
		return mar;
	}
	
	public void setMAR(String mar) {
		//elimina os 4 bits mais significativos devido ao seu tamanho de 12
		this.mar = mar.substring(4, mar.length());
	}
	
	public String getMBR() {
		return mbr;
	}
	
	public void populaMBR() {
		this.mbr = this.saidaDeslocador;
	}
	
	public void setMBR(String conteudo)
	{
		this.mbr = conteudo;
	}
	
	public void executarALU() throws Exception
	{
		this.saidaALU = this.alu.operar(this.getMIR(MIR.ALU), this.saidaAMUX, this.getLatchB());
	}
	
	public void executarAMUX()
	{
		this.saidaAMUX = this.amux.selecionar(this.getMIR(MIR.AMUX), this.getLatchA(), this.getMBR());
	}
	
	public String getMicroinstrucao(String address)
	{
		return this.memoriaDeControle.getMicroinstrucao(address);
	}
	
	public void populaMIR()
	{
		String address = this.getMPC();
		this.mir.setMIR(this.getMicroinstrucao(address));
	}
	
	public String getMIR(int campo)
	{
		return this.mir.getCampo(campo);
	}
	
	public void populaBarramento(int barramento)
	{
		int index;
		if (barramento == Mic1.BARRAMENTO_A)
		{
			index = this.decodificadorA.decodificar(this.getMIR(MIR.A));	
			this.barramentoA = this.bancoDeRegistradores.getRegistrador(index);
		}	
		else if (barramento == Mic1.BARRAMENTO_B)
		{
			index = this.decodificadorB.decodificar(this.getMIR(MIR.B));
			this.barramentoB = this.bancoDeRegistradores.getRegistrador(index);
		}
		else if (barramento == Mic1.BARRAMENTO_C)
		{
			this.barramentoC = this.saidaDeslocador;
		}
		//else //if (barramento == Mic1.BARRAMENTO_B)
		//	index = this.decodificadorB.decodificar(this.getMIR(MIR.B));
		//else
		//	index = this.decodificadorC.decodificar(valor);
		 
	}
	
	public void populaRegistradorC()
	{
		int index = this.decodificadorC.decodificar(this.getMIR(MIR.C));
		this.bancoDeRegistradores.setRegistrador(index, this.barramentoC);
	}
	
	public void atualizaINCR()
	{
		this.incr.setValue(this.getMPC());
	}
	
	public String getINCR()
	{
		return this.incr.getValue();
	}
	
	public void executarDeslocador()
	{
		this.saidaDeslocador = this.deslocador.deslocar(this.getMIR(MIR.SH), this.saidaALU);
	}
	
	public void executarMMUX()
	{
		this.saidaMMUX = this.mmux.selecionar(this.getMIR(MIR.COND), this.getINCR(), this.getMIR(MIR.ADDR), this.alu.getN(), this.alu.getZ());
	}

	@Override
	public String toString() {
		
		StringBuffer s = new StringBuffer();
		
		s.append("Mic1\n");
		s.append(this.bancoDeRegistradores.toString()+"\n\n");
		s.append(this.incr.toString()+"\n\n");
		s.append("MAR = "+this.mar+"\n\n");
		s.append("MBR = "+this.mbr+"\n\n");
		s.append(this.mir.toString()+"\n\n");
		s.append("MPC = "+this.mpc+"\n\n");
	
		return s.toString();
	}
	
	
	
}
